import React from 'react';
import PropTypes from 'prop-types';
import { get, template } from 'lodash';
import { stripesConnect } from '@folio/stripes/core';

import { buildUrl, makeQueryFunction, StripesConnectedSource } from '@folio/stripes/smart-components';

import filterConfig from './filterConfig';
import { BookInStorageSearch } from '../views';
import { BASE_PAHT } from '../constants';


const INITIAL_RESULT_COUNT = 30;
const RESULT_COUNT_INCREMENT = 30;

const compileQuery = template(
  '(bookseller = "%{query}*" or beginBarcode >= "%{query}" or ndBarcode <= "%{query}" or yearFunding = "%{query}*" or colourCode = "%{query}*")',

  { interpolate: /%{([\s\S]+?)}/g }
);

class BookInStorageSearchContainer extends React.Component {
  static manifest = Object.freeze({
    initializedFilterConfig: { initialValue: false },
    query: { initialValue: { sort: 'inDate' } },
    resultCount: { initialValue: INITIAL_RESULT_COUNT },
    resultOffset: { initialValue: 0 },
    records: {
      type: 'okapi',
      records: 'bookInStorages',
      resultOffset: '%{resultOffset}',
      perRequest: 100,
      path: 'bookInStorages',
      GET: {
        params: {
          query: makeQueryFunction(
            'cql.allRecords=1',
            // TODO: Refactor/remove this after work on FOLIO-2066 and RMB-385 is done
            (parsedQuery, props, localProps) => localProps.query.query.trim().replace('*', '').split(/\s+/)
              .map(query => compileQuery({ query }))
              .join(' and '),
            {
              'inDate': 'inDate',
              'bookseller': 'bookseller',
              'beginBarcode': 'beginBarcode',
              'endBarcode': 'endBarcode',
              'totality': 'totality',
              'yearFunding': 'yearFunding',
              'storage': 'storage',
              'colourCode': 'colourCode',
              'status': 'status',
              'remark': 'remark',
            },
            filterConfig,
            2,
          ),
        },
        staticFallback: { params: {} },
      },
    },
  });

  static propTypes = {
    children: PropTypes.node,
    location: PropTypes.object,
    match: PropTypes.object,
    history: PropTypes.object,
    resources: PropTypes.shape({
      patronGroups: PropTypes.shape({
        records: PropTypes.arrayOf(PropTypes.object),
      }),
    }).isRequired,
    mutator: PropTypes.shape({
      initializedFilterConfig: PropTypes.shape({
        replace: PropTypes.func.isRequired,
      }),
      records: PropTypes.shape({
        POST: PropTypes.func.isRequired,
      }),
      query: PropTypes.shape({
        update: PropTypes.func.isRequired,
        replace: PropTypes.func.isRequired,
      }),
      loans: PropTypes.shape({
        GET: PropTypes.func.isRequired,
        reset: PropTypes.func.isRequired,
      }),
      resultOffset: PropTypes.shape({
        replace: PropTypes.func.isRequired,
      }),
    }).isRequired,
    stripes: PropTypes.shape({
      logger: PropTypes.object
    }).isRequired,
  }

  constructor(props) {
    super(props);

    this.logger = props.stripes.logger;
    this.log = this.logger.log.bind(this.logger);
    this.searchField = React.createRef();
  }

  componentDidMount() {
    this.source = new StripesConnectedSource(this.props, this.logger);
    if (this.searchField.current) {
      this.searchField.current.focus();
    }
  }

  componentDidUpdate() {
    this.source.update(this.props);
  }

  onNeedMoreData = (askAmount, index) => {
    const { resultOffset } = this.props.mutator;

    if (this.source) {
      if (resultOffset && index >= 0) {
        this.source.fetchOffset(index);
      } else {
        this.source.fetchMore(RESULT_COUNT_INCREMENT);
      }
    }
  };

  querySetter = ({ nsValues, state }) => {
    const { location : locationProp, history } = this.props;
    if (nsValues.query) {
      nsValues.query = nsValues.query.replace('*', '');
    }
    let location = locationProp;
    // modifying the location hides the user detail view if a search/filter is triggered.
    if (state.changeType !== 'init.reset' && !location.pathname.endsWith('bookInStorage')) {
      const pathname = BASE_PAHT;
      location = { ...locationProp, pathname };
    }

    const url = buildUrl(location, nsValues);
    history.push(url);
  }

  queryGetter = () => {
    return get(this.props.resources, 'query', {});
  }

  render() {
    if (this.source) {
      this.source.update(this.props);
    }

    return (
      <BookInStorageSearch
        source={this.source}
        initialSearch="?sort=-inDate"
        onNeedMoreData={this.onNeedMoreData}
        queryGetter={this.queryGetter}
        querySetter={this.querySetter}
        {...this.props}
      >
        { this.props.children }
      </BookInStorageSearch>
    );
  }
}

export default stripesConnect(BookInStorageSearchContainer);
